package oop.ex1.filescript;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import oop.ex1.actions.*;
import oop.ex1.filters.*;
import oop.ex1.orders.*;

public class Subsection1 {

	// data members:
	protected ArrayList<ArrayList<Filter>> _filters;
	protected ArrayList<Action> _actions;
	protected Comparator<File> _order = new AbsOrder();
	protected ArrayList<String> _comments;
	
	//Constructor
	public Subsection1(){
		_filters = new ArrayList<ArrayList<Filter>>();
		_actions = new ArrayList<Action>();
		_comments = new ArrayList<String>();
	}
	
	public void addAction(Action action){
		_actions.add(action);
	}
	
	public ArrayList<Action> getActions() {
		return _actions;
	}
	
	public void addFilter(Filter filter){
		_filters.get(_filters.size() - 1).add(filter);
	}
	
	public void addFilterColumn(){
		_filters.add(new ArrayList<Filter>());
	}
	
	public void changeOrder(Comparator<File> order){
		_order = order;
	}
	
	public void addComment(String comment){
		_comments.add(comment);
	}

	public void DoAction(File path) throws IOException {
		hasLegalActions();
		TreeSet<File> fullFileList  = new TreeSet<File>();
		fullFileList.addAll(traverseAllFiles(path));
		TreeSet<File> filteredFileList = new TreeSet<File>(_order);
		filteredFileList.addAll(generateFilteredFileList(fullFileList));
		File file = null;
		Iterator<File> filteredFileListItarator = filteredFileList.iterator();
		//printing the comments:
		for(String comment : _comments){
			System.out.println(comment);
		}
		while(filteredFileListItarator.hasNext()){
			file = filteredFileListItarator.next();
			for (Action action : _actions) {
				try {
					action.doAction(file);
				} catch (IOException e) {
					throw new IOException();
				}
			}
		}
	}

	private TreeSet<File> generateFilteredFileList(TreeSet<File> fullFileList) {
		TreeSet<File> union = new TreeSet<File>();
		TreeSet<File> filteredFileList = new TreeSet<File>(fullFileList);
		// Or operation: fileList is added with the files that every filter has
		// approved:
		for (ArrayList<Filter> filterIntersection : _filters) {
			for (Filter currentFilter : filterIntersection) {
				union.addAll(currentFilter.filter(fullFileList));
			}
			filteredFileList.retainAll(union);
			union.clear();
		}
		return filteredFileList;
	}
	
	/**
	 * A method that traverses a directory for it files including sub-folders
	 * @param path The directory path to traverse
	 * @return A list of Files contained in the directory and sub-directories
	 */
	private static ArrayList<File> traverseAllFiles(File path) {
		ArrayList<File> list = new ArrayList<File>();
		list = traverseAllFilesHelper(path, list);
		return list;
	}

	// A helper method to recursively search for all files
	private static ArrayList<File> traverseAllFilesHelper(File path,
			ArrayList<File> files) {
		if (path.isFile()) {
			files.add(path);
		}
		if (path.isDirectory()) {
			String[] children = path.list();
			for (int i = 0; i < children.length; i++) {
				traverseAllFilesHelper(new File(path, children[i]), files);
			}
		}
		return files;
	}
	
	// checks whether the ACTION section is technically fine, i.e. not empty
	// or MOVE/REMOVE followed by other actions
	// @param actionList
	// @return false - if there are no actions in the ACTION section, or the
	// MOVE/REMOVE action is followed by an other action true - otherwise
	public boolean hasLegalActions() {
		if (_actions.isEmpty()) {
			throw new IllegalArgumentException();
		}
		for (Action action : _actions) {
			if (action instanceof MoveAction || action instanceof RemoveAction) {
				if (_actions.indexOf(action) != _actions.size() - 1) {
					throw new IllegalArgumentException();
				}
			}
		}
		return true;
	}
}